package luke4fun.wheresmymoney;

import android.app.ActionBar;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.Calendar;
import java.util.List;

import luke4fun.wheresmymoney.adapter.list.BasicAdapter;
import luke4fun.wheresmymoney.adapter.list.impl.CategoryListAdapter;
import luke4fun.wheresmymoney.bean.CategoryBean;
import luke4fun.wheresmymoney.common.CommonConstants;
import luke4fun.wheresmymoney.db.AccDBHelper;
import luke4fun.wheresmymoney.db.DBConstants;
import luke4fun.wheresmymoney.db.ItemDAO;
import luke4fun.wheresmymoney.db.StoreDAO;
import luke4fun.wheresmymoney.domain.Item;
import luke4fun.wheresmymoney.domain.Store;
import luke4fun.wheresmymoney.fragments.DatePickerFragment;
import luke4fun.wheresmymoney.service.async.AsyncAutoCompTask;
import luke4fun.wheresmymoney.service.async.CategoryAsyncTask;
import luke4fun.wheresmymoney.util.FormatUtil;

public class DoAccActivity extends FragmentActivity {

	private AccDBHelper dbHelper;
	private SQLiteDatabase db;

	private RelativeLayout rLayout;
	
	private EditText totalExpenseInput;
	private EditText priceInput;
	private EditText expenseDateInput;
	
	private TextView emptyList;
	private ListView categoryList;
	private BasicAdapter<CategoryBean> adapter;

	private AutoCompleteTextView itemInput;
	private AutoCompleteTextView storeInput;

	private ArrayAdapter<String> autoItemAdapter;
	private ArrayAdapter<String> autoStoreAdapter;

	private ImageButton addRowBtn;

	private Context context;
	private View actionBarView;
	
	private int selectedCategoryPos = -1;
	private int id = CommonConstants.NEW_VIEW_ID;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_do_accounting);
		context = this;
		rLayout = (RelativeLayout) findViewById(R.id.do_acc_layout);
		
		ActionBar actionBar = getActionBar();
		actionBar.setDisplayHomeAsUpEnabled(false);
		actionBar.setDisplayShowTitleEnabled(false);
		actionBar.setDisplayUseLogoEnabled(false);
		actionBar.setDisplayShowHomeEnabled(false);
		actionBar.setDisplayShowCustomEnabled(true);
		actionBar.setCustomView(R.layout.menu_layout_edit);
		
		initView();
		setListeners();
	}
	
	@Override
	public void onStart() {
		super.onStart();
		dbHelper = new AccDBHelper(context);
	}
	
	@Override
	public void onResume() {
		super.onResume();
		setAutoComp();
		refresh();
	}
	
	@Override
	public void onPause() {
		super.onPause();
		if (dbHelper != null) {
			dbHelper.close();
		}
	}
	
	private void initView() {
		totalExpenseInput = (EditText) findViewById(R.id.total_expense);
		priceInput = (EditText) findViewById(R.id.priceInput);
		expenseDateInput = (EditText) findViewById(R.id.expensedateInput);
		
		emptyList = (TextView) findViewById(R.id.empty_list);
		categoryList = (ListView) findViewById(R.id.categories);
		adapter = new CategoryListAdapter(context);
		categoryList.setAdapter(adapter);
		categoryList.setEmptyView(emptyList);

		// set up autocomplete textview
		itemInput  = (AutoCompleteTextView) findViewById(R.id.itemInput);
		storeInput = (AutoCompleteTextView) findViewById(R.id.storeInput);

		// set up adapter
		autoItemAdapter  = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
		autoStoreAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
		itemInput.setAdapter(autoItemAdapter);
		storeInput.setAdapter(autoStoreAdapter);

		addRowBtn = (ImageButton) findViewById(R.id.add_row_btn);
		
		// set up datepicker dialog
		final Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH);
		int day = c.get(Calendar.DAY_OF_MONTH);
		expenseDateInput.setText((month + 1) + "/" + day + "/" + year);
		
		// get ActionBar custom view
		actionBarView = getActionBar().getCustomView();
	}

	private void setAutoComp() {
		new AsyncAutoCompTask(this, autoItemAdapter, 0).execute();
		new AsyncAutoCompTask(this, autoStoreAdapter, 2).execute();
	}
	
	private void setListeners() {
		expenseDateInput.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				DialogFragment dialog = DatePickerFragment.newInstance(v);
				dialog.show(getSupportFragmentManager(), "datepicker");
			}
		});
		
		// set onItemClickListener to set color when cliking on an item
		categoryList.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parentView, View selectedView, int position, long id) {
				// get previous selected item
				if (selectedCategoryPos != -1) {
					CategoryBean bean = (CategoryBean) adapter.getItem(selectedCategoryPos);
					bean.setSelected(false);
				}
				
				// set background color for the selected item
				CategoryBean bean = (CategoryBean) adapter.getItem(position);
				bean.setSelected(true);
				
				((TextView) selectedView.findViewById(R.id.category_txt)).setTextAppearance(context, R.style.selected);
				selectedView.setBackgroundColor(bean.getColor());
				selectedCategoryPos = position;
				
				adapter.notifyDataSetChanged();
			}
		});
		
		addRowBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// create a new linear layout
				LinearLayout lLayout = new LinearLayout(context);
				lLayout.setId(id);
				
				// add item input EditText
				AutoCompleteTextView itemInput = new AutoCompleteTextView(context);
				itemInput.setId(CommonConstants.NEW_VIEW_ID * 2);
				itemInput.setHint(getResources().getString(R.string.item));
				LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT);
				p.weight = 2;
				itemInput.setLayoutParams(p);
				itemInput.setThreshold(1);
				itemInput.setAdapter(autoItemAdapter);
				lLayout.addView(itemInput);
				
				// add price input EditText
				EditText priceInput = new EditText(context);
				priceInput.setId(CommonConstants.NEW_VIEW_ID * 2 + 1);
				priceInput.setHint(getResources().getString(R.string.price));
				priceInput.setInputType(InputType.TYPE_CLASS_NUMBER);
				LinearLayout.LayoutParams p2 = new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT);
				p2.weight = 1;
				priceInput.setLayoutParams(p2);
				lLayout.addView(priceInput);
				
				// add the created linear layout to the relative layout
				RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
				if (id == CommonConstants.NEW_VIEW_ID) {
					params.addRule(RelativeLayout.BELOW, R.id.detail_line);
				} else {
					params.addRule(RelativeLayout.BELOW, id-1);
				}
				id++;
				
				lLayout.setLayoutParams(params);
				rLayout.addView(lLayout);

				// adjust layout
				LinearLayout detailLine = (LinearLayout) rLayout.findViewById(R.id.detail_line);
				int height = detailLine.getMeasuredHeight();
				v.setTranslationY(v.getTranslationY() + height);
				
				rLayout.getLayoutParams().height = rLayout.getMeasuredHeight() + height;
			}
		});
		
		actionBarView.findViewById(R.id.action_ok).setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				saveData();
				((Activity) context).finish();
			}
		});
		
		actionBarView.findViewById(R.id.action_cancel).setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				clearData();
				((Activity) context).finish();
			}
		});
	}
	
	public void saveData() {
		hideKeyboard();
		save();
		clear();
	}
	
	public void clearData() {
		hideKeyboard();
		clear();
	}

	/**
	 * 1) insert total expense
	 * 2) if has additional infos, add the infos
	 */
	private void save() {
		db = dbHelper.getWritableDatabase();
		db.beginTransaction();

		try {
			// parse date to milliseconds
			long dataTime = FormatUtil.parseDateFromMMddyyyy(expenseDateInput.getText().toString()).getTime();
			// save category
			long categoryId = (selectedCategoryPos == -1) ? -1 : ((CategoryBean) adapter.getItem(selectedCategoryPos)).getId();
			// save store
			long storeId = getStoreId(storeInput.getText().toString());
			// get price
			Integer price = Integer.valueOf(totalExpenseInput.getText().toString());
			// item
			long itemId = -1;
			
			ContentValues cv = new ContentValues();
			// update category frequence
			if ((selectedCategoryPos != -1)) {
				CategoryBean bean = (CategoryBean) adapter.getItem(selectedCategoryPos);
				cv.put(DBConstants.CATEGORY_ID, bean.getId());
				cv.put(DBConstants.CATEGORY_COLOR, bean.getColor());
				cv.put(DBConstants.CATEGORY_NAME, bean.getName());
				cv.put(DBConstants.CATEGORY_FREQUENCE, bean.getFrequence()+1);
				db.update(DBConstants.TABLE_CATEGORY, cv, DBConstants.CATEGORY_ID + "=?", new String[] {bean.getId() + ""});
			}
			// 1) insert total expense
			cv.clear();
			cv.put(DBConstants.RECORD_PID, -1);
			cv.put(DBConstants.RECORD_PRICE, price);
			cv.put(DBConstants.RECORD_DATATIME, dataTime);
			cv.put(DBConstants.RECORD_ITEM, -1);
			cv.put(DBConstants.RECORD_CATEGORY, categoryId);
			cv.put(DBConstants.RECORD_STORE, storeId);
			long pid = db.insert(DBConstants.TABLE_RECORD, null, cv);
			
			// 2) save item
			if (!TextUtils.isEmpty( itemInput.getText().toString() )) {
				
				itemId = insertItem(itemInput.getText().toString());
				price = TextUtils.isEmpty(priceInput.getText()) ? 
							null : Integer.parseInt(priceInput.getText().toString());
				cv.put(DBConstants.RECORD_PID, pid);
				cv.put(DBConstants.RECORD_PRICE, price);
				cv.put(DBConstants.RECORD_ITEM, itemId);
				
				db.insert(DBConstants.TABLE_RECORD, null, cv);
				
			}
			
			// save dynamically created input
			String itemText;
			String priceText;
			for (int i=id-1; i>=CommonConstants.NEW_VIEW_ID; i--) {
				LinearLayout lLayout = (LinearLayout) rLayout.findViewById(i);
				itemText  = ((EditText) lLayout.findViewById(CommonConstants.NEW_VIEW_ID*2)).getText().toString();
				priceText = ((EditText) lLayout.findViewById(CommonConstants.NEW_VIEW_ID*2+1)).getText().toString();
				
				if (!TextUtils.isEmpty(itemText)) {
					itemId = insertItem(itemText);
					price = TextUtils.isEmpty(priceText) ? null : Integer.parseInt(priceText);

					cv.put(DBConstants.RECORD_PID, pid);
					cv.put(DBConstants.RECORD_ITEM, itemId);
					cv.put(DBConstants.RECORD_PRICE, price);
					db.insert(DBConstants.TABLE_RECORD, null, cv);
				}
			}
			db.setTransactionSuccessful();
		} catch (NumberFormatException e) {
			Log.e("ZJ", "parsing price error: " + e.getMessage());
		} catch (Exception e) {
			Log.e("ZJ", "saving accounting error: " + e.getMessage());
		}
		db.endTransaction();
		db.close();
	}

	private void clear() {
		totalExpenseInput.setText("");
		priceInput.setText("");
		itemInput.setText("");
		storeInput.setText("");

		final Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH);
		int day = c.get(Calendar.DAY_OF_MONTH);

		// set up datepicker dialog
		expenseDateInput.setText((month + 1) + "/" + day + "/" + year);
		
		LinearLayout detailLine = (LinearLayout) rLayout.findViewById(R.id.detail_line);
		int height = detailLine.getMeasuredHeight();
		int translationY = 0;
		
		// delete dynamically created input
		for (int i=id-1; i>=CommonConstants.NEW_VIEW_ID; i--) {
			rLayout.removeView(rLayout.findViewById(i));
			translationY -= height;
		}
		id = CommonConstants.NEW_VIEW_ID;
		
		// adjust layout
		addRowBtn.getLayoutParams();
		addRowBtn.setTranslationY(addRowBtn.getTranslationY() + translationY);
		
		rLayout.getLayoutParams().height = rLayout.getMeasuredHeight() + translationY;
	}

	/**
	 * check if item is already in database if not, insert item and return id
	 * 
	 * @return itemId
	 */
	private long insertItem(String item) {
		ItemDAO itemDao = ItemDAO.getInstance();
		List<Item> itemList = itemDao.queryItem(db, item);
		Log.d("ZJ", "insertItem... itemList size= " + itemList.size());

		return (itemList.size() == 0) ? 
				itemDao.insertItem(db, item) : itemList.get(0).getId();
	}

	/**
	 * check if store is alreay in database if it is, return id; if not, insert
	 * store and return id
	 * 
	 * @return
	 */
	private long getStoreId(String store) {
        if (TextUtils.isEmpty(store)) {
            return -1;
        }

		StoreDAO storeDao = StoreDAO.getInstance();
		List<Store> storeList = storeDao.queryStore(db, store);
		Log.d("ZJ", "getStoreId... storeList size= " + storeList.size());
		
		return (storeList.size() == 0) ? 
				storeDao.insertStore(db, store) : storeList.get(0).getId();
	}
	
	public void refresh() {
		new CategoryAsyncTask(context, adapter).execute();
	}

	public void hideKeyboard() {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(itemInput.getWindowToken(), 0);
	}
}
